#if defined(ARCTIC)
/**
 @file sys_usw_sync_ether.c

 @date 2022-1-11

 @version v1.0

 sync ethernet function of Arctic
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "ctc_macro.h"
#include "ctc_debug.h"
#include "ctc_warmboot.h"

#include "sys_usw_common.h"
#include "sys_usw_register.h"
#include "sys_usw_wb_common.h"

#include "sys_usw_dmps.h"
#include "sys_usw_sync_ether.h"
#include "sys_usw_chip.h"

#include "drv_api.h"

#define TOTAL_SERDES 160
#define SYS_AT_SYNC_ETHER_TBL_NUM_PER_CORE 40

int32
sys_at_sync_ether_set_cfg(uint8 lchip, uint8 sync_ether_clock_id, void* sync_ether_cfg)
{
    uint32 cmd = 0;
    uint32 value = 0;
    uint32 tmp_divide[2] = {0};
    uint8 clock_select = 0;
    uint8 clock_select_logic = 0;
    uint8 gchip = 0;
    uint32 port_type = 0;
    uint8 index = 0;
    uint8 tmp_lchip = 0;
    sys_dmps_serdes_info_t serdes_info;
    sys_dmps_serdes_info_t serdes_info1;/*for get logic serdes*/
    ctc_sync_ether_cfg_t* p_sync_ether_cfg = (ctc_sync_ether_cfg_t*) sync_ether_cfg;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    HssLaneCfg_m lane_cfg;
    CtcHsCtlSyncECfg_m syncE_cfg;

    sal_memset(&syncE_cfg, 0, sizeof(syncE_cfg));
    /*debug info*/
    SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));

    dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_sync_ether_cfg->recovered_clock_lport);
    SYS_MAP_GPORT_TO_LCHIP1(dmps_port_info.gport,tmp_lchip);
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (!(SYS_DMPS_NETWORK_PORT == port_type || SYS_DMPS_INACTIVE_NETWORK_PORT == port_type))
    {
        SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " MAC is not used \n");
        return CTC_E_INVALID_CONFIG;
    }

    sal_memset(&serdes_info, 0, sizeof(sys_dmps_serdes_info_t));
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SERDES, (void *)&serdes_info));
    sal_memset(&serdes_info1, 0, sizeof(sys_dmps_serdes_info_t));
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SERDES_LOGIC, (void *)&serdes_info1));

    /*
    *core0:160 serdes, 40 CtcHsGroup, per CtcHsGroup is consist of 4 serdes
    *core1:160 serdes, 40 CtcHsGroup, per CtcHsGroup is consist of 4 serdes
    */
    tmp_lchip = sys_usw_vchip_get_core_pp_base(tmp_lchip);
    index = (serdes_info.serdes_id[0]) / 4;
    if(index >= SYS_AT_SYNC_ETHER_TBL_NUM_PER_CORE)
    {
        index -= SYS_AT_SYNC_ETHER_TBL_NUM_PER_CORE;
        tmp_lchip += PP_NUM_PER_CORE;
    }
    clock_select = serdes_info.serdes_id[0] % 4;
    clock_select_logic = serdes_info1.serdes_id[0] % 8;
    SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "index=%d,base=%d,serdes_id_phy=%d,serdes_id_logic=%d\n",
                        index, index, serdes_info.serdes_id[0], serdes_info1.serdes_id[0]);
    /* CtcHsCtlSyncECfg  serdes_id core0:0~159 core1:160~319 */

    /* set reset */
    value = 1;
    SetCtcHsCtlSyncECfg(V, cfgClkResetEtherClkPrimary_f + sync_ether_clock_id, &syncE_cfg, value);

    /* set config */
    tmp_divide[1] = (p_sync_ether_cfg->divider  >> 16);/* set divider config */
    tmp_divide[0] = ((p_sync_ether_cfg->divider << 16) | p_sync_ether_cfg->divider_frac);
    SetCtcHsCtlSyncECfg(A, cfgClkDividerEtherClkPrimary_f + sync_ether_clock_id, &syncE_cfg, tmp_divide);

    /* set linkstatus, if serdes single isn't detected, outclock is 0*/
    value = p_sync_ether_cfg->link_status_detect_en ? 0 : 1;
    SetCtcHsCtlSyncECfg(V, cfgFastLinkFailureDisPrimary_f + sync_ether_clock_id, &syncE_cfg, value);

    /*bitmap control 1 of 4 serdes lane recover clock output*/
    value = p_sync_ether_cfg->clock_output_en ?  (1 << clock_select) : 0;
    SetCtcHsCtlSyncECfg(V, cfgEtherClkSelectPrimary_f + sync_ether_clock_id, &syncE_cfg, value);

    /*0 is invalid value for clock not output when disable*/
    value = p_sync_ether_cfg->clock_output_en ? (1<<clock_select_logic) : 0;
    SetCtcHsCtlSyncECfg(V, cfgLinkStatusSelectPrimary_f + sync_ether_clock_id, &syncE_cfg, value);
    cmd = DRV_IOW(CtcHsCtlSyncECfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(tmp_lchip, index, DRV_CMD_PP_EN(cmd), &syncE_cfg));

    p_usw_sync_ether_master[lchip]->recovered_clock_lport[sync_ether_clock_id] = p_sync_ether_cfg->recovered_clock_lport;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_SYNC_ETHER, SYS_WB_APPID_SYNCE_SUBID_MASTER, 1);

    /* set reset */
    value = 0;
    SetCtcHsCtlSyncECfg(V, cfgClkResetEtherClkPrimary_f + sync_ether_clock_id, &syncE_cfg, value);
    cmd = DRV_IOW(CtcHsCtlSyncECfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(tmp_lchip, index, DRV_CMD_PP_EN(cmd), &syncE_cfg));

    cmd = DRV_IOR(HssLaneCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(tmp_lchip, index, DRV_CMD_PP_EN(cmd), &lane_cfg));
    SetHssLaneCfg(V, cfgPmaReady4SyncEMaskLane0_f, &lane_cfg, 0x3d);
    SetHssLaneCfg(V, cfgPmaReady4SyncEMaskLane1_f, &lane_cfg, 0x3d);
    SetHssLaneCfg(V, cfgPmaReady4SyncEMaskLane2_f, &lane_cfg, 0x3d);
    SetHssLaneCfg(V, cfgPmaReady4SyncEMaskLane3_f, &lane_cfg, 0x3d);
    cmd = DRV_IOW(HssLaneCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(tmp_lchip, index, DRV_CMD_PP_EN(cmd), &lane_cfg));

    return CTC_E_NONE;

}

int32
sys_at_sync_ether_get_cfg(uint8 lchip, uint8 sync_ether_clock_id, void* sync_ether_cfg)
{
    uint32 cmd = 0;
    uint32 value = 0;
    uint32 tmp_divide[2] = {0};
    uint8 gchip = 0;
    uint8 clock_select = 0;
    uint32 port_type = 0;
    uint8 index = 0;
    uint8 tmp_lchip = 0;
    sys_dmps_serdes_info_t serdes_info;
    ctc_sync_ether_cfg_t* p_sync_ether_cfg = (ctc_sync_ether_cfg_t*) sync_ether_cfg;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    CtcHsCtlSyncECfg_m syncE_cfg;
    SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&syncE_cfg, 0, sizeof(syncE_cfg));
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    /*read config*/
    dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_sync_ether_cfg->recovered_clock_lport);
    SYS_MAP_GPORT_TO_LCHIP1(dmps_port_info.gport,tmp_lchip);
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    if (!(SYS_DMPS_NETWORK_PORT == port_type || SYS_DMPS_INACTIVE_NETWORK_PORT == port_type))
    {
        SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " MAC is not used \n");
        return CTC_E_INVALID_CONFIG;
    }

    sal_memset(&serdes_info, 0, sizeof(sys_dmps_serdes_info_t));
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SERDES, (void *)&serdes_info));

    /*
    *core0 : 160 serdes, 40 CtcHsGroup, per CtcHsGroup is consist of 4 serdes
    *core1 : 160 serdes, 40 CtcHsGroup, per CtcHsGroup is consist of 4 serdes
    */
    tmp_lchip = sys_usw_vchip_get_core_pp_base(tmp_lchip);
    index = (serdes_info.serdes_id[0]) / 4;
    clock_select = serdes_info.serdes_id[0] % 4;
    SYS_SYNC_ETHER_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "index=%d,base=%d,serdes_id_phy=%d\n",
                           index, index, serdes_info.serdes_id[0]);
    /* CtcHsCtlSyncECfg  serdes_id core0:0~159 core1:160~319 */
    cmd = DRV_IOR(CtcHsCtlSyncECfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(tmp_lchip, index, DRV_CMD_PP_EN(cmd), &syncE_cfg));
    GetCtcHsCtlSyncECfg(A, cfgClkDividerEtherClkPrimary_f + sync_ether_clock_id, &syncE_cfg,tmp_divide);
    p_sync_ether_cfg->divider = ((tmp_divide[1] << 16) | tmp_divide[0] >> 16);
    p_sync_ether_cfg->divider_frac = tmp_divide[0] &0xFFFF;
    
    value = GetCtcHsCtlSyncECfg(V, cfgFastLinkFailureDisPrimary_f + sync_ether_clock_id, &syncE_cfg);
    p_sync_ether_cfg->link_status_detect_en = value ? 0 : 1;

    value = GetCtcHsCtlSyncECfg(V, cfgEtherClkSelectPrimary_f + sync_ether_clock_id, &syncE_cfg);
    p_sync_ether_cfg->clock_output_en = CTC_IS_BIT_SET(value, clock_select);

    return CTC_E_NONE;
}

#endif


